package com.mini.grpc.common;

import com.mini.grpc.serialization.Marshaller;

import java.util.Objects;

/**
 * MethodDescriptor描述一个RPC方法的元数据。
 *
 * @param <ReqT> 请求类型
 * @param <RespT> 响应类型
 */
public final class MethodDescriptor<ReqT, RespT> {

    /**
     * RPC方法类型
     */
    public enum MethodType {
        /**
         * 一元调用：客户端发送单个请求并获取单个响应
         */
        UNARY,
        
        /**
         * 服务端流式调用：客户端发送单个请求并获取流式响应
         */
        SERVER_STREAMING,
        
        /**
         * 客户端流式调用：客户端发送流式请求并获取单个响应
         */
        CLIENT_STREAMING,
        
        /**
         * 双向流式调用：客户端和服务端都可以发送流式消息
         */
        BIDI_STREAMING
    }
    
    private final String fullMethodName;
    private final MethodType methodType;
    private final Marshaller<ReqT> requestMarshaller;
    private final Marshaller<RespT> responseMarshaller;
    
    private MethodDescriptor(
            String fullMethodName,
            MethodType methodType,
            Marshaller<ReqT> requestMarshaller,
            Marshaller<RespT> responseMarshaller) {
        this.fullMethodName = fullMethodName;
        this.methodType = methodType;
        this.requestMarshaller = requestMarshaller;
        this.responseMarshaller = responseMarshaller;
    }
    
    /**
     * 获取方法的完整名称
     *
     * @return 方法的完整名称，格式为"服务名/方法名"
     */
    public String getFullMethodName() {
        return fullMethodName;
    }
    
    /**
     * 获取服务名
     *
     * @return 服务名
     */
    public String getServiceName() {
        int index = fullMethodName.indexOf('/');
        return index == -1 ? fullMethodName : fullMethodName.substring(0, index);
    }
    
    /**
     * 获取方法名
     *
     * @return 方法名
     */
    public String getMethodName() {
        int index = fullMethodName.indexOf('/');
        return index == -1 ? "" : fullMethodName.substring(index + 1);
    }
    
    /**
     * 获取方法类型
     *
     * @return 方法类型
     */
    public MethodType getMethodType() {
        return methodType;
    }
    
    /**
     * 获取方法类型（别名方法）
     *
     * @return 方法类型
     */
    public MethodType getType() {
        return methodType;
    }
    
    /**
     * 获取请求序列化器
     *
     * @return 请求序列化器
     */
    public Marshaller<ReqT> getRequestMarshaller() {
        return requestMarshaller;
    }
    
    /**
     * 获取响应序列化器
     *
     * @return 响应序列化器
     */
    public Marshaller<RespT> getResponseMarshaller() {
        return responseMarshaller;
    }
    
    /**
     * 创建一个新的方法描述符构建器
     *
     * @param <ReqT> 请求类型
     * @param <RespT> 响应类型
     * @return 新的构建器
     */
    public static <ReqT, RespT> Builder<ReqT, RespT> newBuilder() {
        return new Builder<>();
    }
    
    /**
     * 方法描述符构建器
     *
     * @param <ReqT> 请求类型
     * @param <RespT> 响应类型
     */
    public static final class Builder<ReqT, RespT> {
        private String fullMethodName;
        private MethodType methodType;
        private Marshaller<ReqT> requestMarshaller;
        private Marshaller<RespT> responseMarshaller;
        
        private Builder() {
        }
        
        /**
         * 设置方法的完整名称
         *
         * @param fullMethodName 方法的完整名称，格式为"服务名/方法名"
         * @return 构建器本身
         */
        public Builder<ReqT, RespT> setFullMethodName(String fullMethodName) {
            this.fullMethodName = fullMethodName;
            return this;
        }
        
        /**
         * 设置方法类型
         *
         * @param methodType 方法类型
         * @return 构建器本身
         */
        public Builder<ReqT, RespT> setMethodType(MethodType methodType) {
            this.methodType = methodType;
            return this;
        }
        
        /**
         * 设置请求序列化器
         *
         * @param requestMarshaller 请求序列化器
         * @return 构建器本身
         */
        public Builder<ReqT, RespT> setRequestMarshaller(Marshaller<ReqT> requestMarshaller) {
            this.requestMarshaller = requestMarshaller;
            return this;
        }
        
        /**
         * 设置响应序列化器
         *
         * @param responseMarshaller 响应序列化器
         * @return 构建器本身
         */
        public Builder<ReqT, RespT> setResponseMarshaller(Marshaller<RespT> responseMarshaller) {
            this.responseMarshaller = responseMarshaller;
            return this;
        }
        
        /**
         * 构建方法描述符
         *
         * @return 新的方法描述符
         */
        public MethodDescriptor<ReqT, RespT> build() {
            Objects.requireNonNull(fullMethodName, "fullMethodName");
            Objects.requireNonNull(methodType, "methodType");
            Objects.requireNonNull(requestMarshaller, "requestMarshaller");
            Objects.requireNonNull(responseMarshaller, "responseMarshaller");
            return new MethodDescriptor<>(
                    fullMethodName, methodType, requestMarshaller, responseMarshaller);
        }
    }
} 